home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-win32 / win32.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  46KB  |  1,887 lines

  1. /*
  2.  * UAE - The Un*x Amiga Emulator
  3.  *
  4.  * Win32 interface
  5.  *
  6.  * Copyright 1997 Mathias Ortmann
  7.  */
  8.  
  9. #ifdef __GNUC__
  10. #define __int64 long long
  11. #include "machdep/winstuff.h"
  12. #else
  13. #include <windows.h>
  14. #include <ddraw.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <commctrl.h>
  18. #include <commdlg.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <sys/stat.h>
  22. #include <io.h>
  23. #endif
  24.  
  25. #include "config.h"
  26. #include "sysconfig.h"
  27. #include "sysdeps.h"
  28.  
  29. #include "options.h"
  30. #include "gensound.h"
  31. #include "sounddep/sound.h"
  32. #include "uae.h"
  33. #include "threaddep/penguin.h"
  34. #include "memory.h"
  35. #include "custom.h"
  36. #include "events.h"
  37. #include "xwin.h"
  38. #include "keyboard.h"
  39. #include "picasso96.h"
  40.  
  41. #include "osdep/win32gui.h"
  42. #include "resource.h"
  43. #include "osdep/win32.h"
  44.  
  45. extern struct picasso_vidbuf_description picasso_vidinfo;
  46. #define IHF_WINDOWHIDDEN 6
  47.  
  48. static BOOL (WINAPI *pGetOpenFileNameA) (LPOPENFILENAME);
  49. static HRESULT (WINAPI *pDirectDrawCreate) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *);
  50. static HRESULT CALLBACK modesCallback (LPDDSURFACEDESC modeDesc, LPVOID context);
  51.  
  52. HWND hAmigaWnd, hMainWnd;
  53. HINSTANCE hInst;
  54. /*DWORD Keys;*/
  55. static RECT amigawin_rect;
  56.  
  57. drive_specs drives[NUM_DRIVES];
  58. char *start_path = NULL;
  59.  
  60. static LPDIRECTDRAW lpDD;
  61. static LPDIRECTDRAWSURFACE lpDDS;
  62. static LPDIRECTDRAWCLIPPER lpDDC;
  63. static LPDIRECTDRAWPALETTE lpDDP;
  64. static DDSURFACEDESC ddsd;
  65. HANDLE hEmuThread;
  66.  
  67. static HDC hBackDC;
  68. static HBITMAP hBackBM;
  69.  
  70. static CRITICAL_SECTION csDraw;
  71.  
  72. #define TITLETEXT PROGNAME " -- Amiga Display"
  73. char VersionStr[256];
  74. extern int current_width, current_height;
  75.  
  76. static uae_sem_t picasso_switch_sem;
  77.  
  78. static int fullscreen = 0;
  79. int current_width, current_height;
  80. static int current_pixbytes;
  81.  
  82. static int changemode;
  83.  
  84. static int screen_is_picasso = 0;
  85. static int picasso_fullscreen = 1;
  86. int amiga_fullscreen = 1, customsize = 0;
  87.  
  88. int bActive;
  89. int capslock;
  90. int toggle_sound;
  91.  
  92. int process_desired_pri;
  93.  
  94. int cycles_per_instruction = 4;
  95. int good_cpu = 0;
  96.  
  97. BOOL allow_quit_from_property_sheet = TRUE;
  98. BOOL viewing_child = FALSE;
  99.  
  100. static char scrlinebuf[8192];    /* this is too large, but let's rather play on the safe side here */
  101. static int scrindirect;
  102.  
  103. static void set_linemem (void)
  104. {
  105.     if (scrindirect)
  106.     gfxvidinfo.linemem = scrlinebuf;
  107.     else
  108.     gfxvidinfo.linemem = 0;
  109. }
  110.  
  111. /* Keyboard emulation, Win32 helper routines. */
  112. static LPARAM keysdown[256];
  113. static short numkeysdown;
  114.  
  115. int getcapslock (void)
  116. {
  117.     BYTE keyState[256];
  118.  
  119.     GetKeyboardState (keyState);
  120.     return keyState[VK_CAPITAL] & 1;
  121. }
  122.  
  123. int helppressed (void)
  124. {
  125.     return GetAsyncKeyState (VK_END) & 0x8000;
  126. }
  127.  
  128. int shiftpressed (void)
  129. {
  130.     return GetAsyncKeyState (VK_SHIFT) & 0x8000 ? 1 : 0;
  131. }
  132.  
  133. int checkkey (int vkey, LPARAM lParam)
  134. {
  135.     switch (vkey) {
  136.     case VK_SHIFT:
  137.     case VK_LSHIFT:
  138.     case VK_RSHIFT:
  139.     case VK_CONTROL:
  140.     case VK_LCONTROL:
  141.     case VK_RCONTROL:
  142.     case VK_MENU:
  143.     case VK_LMENU:
  144.     case VK_RMENU:
  145.     return GetKeyState (vkey) & 0x8000;
  146.     }
  147.     return GetAsyncKeyState (vkey) & 0x8000;
  148. }
  149.  
  150. /* Mouse emulation, Win32 interface */
  151. static int mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100;
  152. static int mousecl = MAKELONG (160, 100);
  153. int mouseactive;
  154.  
  155. void setmouseactive (int active)
  156. {
  157.     mousedx = (amigawin_rect.right - amigawin_rect.left) / 2;
  158.     mousedy = (amigawin_rect.bottom - amigawin_rect.top) / 2;
  159.     mousecl = MAKELONG (mousedx, mousedy);
  160.     mousecx = amigawin_rect.left + mousedx;
  161.     mousecy = amigawin_rect.top + mousedy;
  162.  
  163.     if (active == mouseactive)
  164.     return;
  165.     mouseactive = active;
  166.  
  167.     if (active) {
  168.     ShowCursor (FALSE);
  169.     SetCursorPos (mousecx, mousecy);
  170.     SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, TITLETEXT " [Mouse active - press Alt-Tab to cancel]");
  171.     ClipCursor (&amigawin_rect);
  172.     } else {
  173.     ShowCursor (TRUE);
  174.     SetWindowText (hMainWnd ? hMainWnd : hAmigaWnd, TITLETEXT);
  175.     ClipCursor (NULL);
  176.     }
  177. }
  178.  
  179. static int hascapture = 0;
  180.  
  181. void setcapture (void)
  182. {
  183.     if (hascapture)
  184.     return;
  185.     hascapture++;
  186.     SetCapture (hAmigaWnd);
  187. }
  188.  
  189. static __inline__ void releasecapture (void)
  190. {
  191.     if (!hascapture)
  192.     return;
  193.     hascapture--;
  194.     ReleaseCapture ();
  195. }
  196.  
  197. static void figure_processor_speed (void)
  198. {
  199.     SYSTEM_INFO sysinfo;
  200.     OSVERSIONINFO osinfo;
  201.     HKEY hKey;
  202.     DWORD value;
  203.     DWORD type, size;
  204.     unsigned long mhz = 0;
  205.     char cpuid[40];
  206.     char *envptr;
  207.  
  208.     vsynctime = -1;
  209.     if ((envptr = getenv ("PROCESSOR_LEVEL")) && atoi (envptr) < 5)
  210.     goto bad_cpu;
  211.  
  212.     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0L, KEY_READ, &hKey) == ERROR_SUCCESS) {
  213.     size = sizeof (value);
  214.     if (RegQueryValueEx (hKey, "~MHz", NULL, &type, (LPBYTE) & value, &size) == ERROR_SUCCESS) 
  215.         mhz = value;
  216.     size = sizeof cpuid;
  217.     if (RegQueryValueEx (hKey, "VendorIdentifier", NULL, &type, (LPBYTE) cpuid, &size) == ERROR_SUCCESS) {
  218.         good_cpu = (strncmp (cpuid, "AuthenticAMD", 12) == 0
  219.             || strncmp (cpuid, "GenuineIntel", 12) == 0);
  220.     }
  221.     RegCloseKey (hKey);
  222.     }
  223.     if (!good_cpu)
  224.     goto bad_cpu;
  225.  
  226. #ifdef FRAME_RATE_HACK
  227.     if (mhz == 0) {
  228.     frame_time_t t;
  229.     DWORD oldpri = GetPriorityClass (GetCurrentProcess ());
  230.  
  231.     write_log ("Calibrating delay loop.. ");
  232.  
  233.     SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS);
  234.     vsynctime = 1;
  235.     t = read_processor_time ();
  236.     Sleep (1001);
  237.     t = 2*read_processor_time () - t;
  238.     Sleep (1);
  239.     t -= read_processor_time ();
  240.     SetPriorityClass (GetCurrentProcess (), oldpri);
  241.  
  242.     MyOutputDebugString ("ok - %.2f BogoMIPS\n", (double)t / 1000000.0);
  243.     vsynctime = t / 50;
  244.     return;
  245.     }
  246. #endif
  247.     if (mhz != 0) {
  248.     vsynctime = mhz * 1000000 / 50;
  249.     return;
  250.     }
  251.     write_log ("Could not determine clock speed of your CPU.\n");
  252.     return;
  253. bad_cpu:
  254.     write_log ("Processor level too low - disabling frame rate hack\n");
  255. }
  256.  
  257. /* DirectDraw stuff*/
  258. char *getddrname (HRESULT ddrval)
  259. {
  260.     switch (ddrval) {
  261.     case DDERR_ALREADYINITIALIZED:
  262.     return "This object is already initialized.";
  263.     case DDERR_BLTFASTCANTCLIP:
  264.     return "Cannot use BLTFAST with Clipper attached to surface.";
  265.     case DDERR_CANNOTATTACHSURFACE:
  266.     return "Cannot attach surface.";
  267.     case DDERR_CANNOTDETACHSURFACE:
  268.     return "Cannot detach surface.";
  269.     case DDERR_CANTCREATEDC:
  270.     return "Cannot create DC Device Context.";
  271.     case DDERR_CANTDUPLICATE:
  272.     return "Cannot duplicate.";
  273.     case DDERR_CANTLOCKSURFACE:
  274.     return "Access to surface refused (no DCI provider).";
  275.     case DDERR_CANTPAGELOCK:
  276.     return "PageLock failure.";
  277.     case DDERR_CANTPAGEUNLOCK:
  278.     return "PageUnlock failure.";
  279.     case DDERR_CLIPPERISUSINGHWND:
  280.     return "Can't set a clip-list for a Clipper which is attached to an HWND.";
  281.     case DDERR_COLORKEYNOTSET:
  282.     return "No source colour-key provided.";
  283.     case DDERR_CURRENTLYNOTAVAIL:
  284.     return "Support unavailable.";
  285.     case DDERR_DCALREADYCREATED:
  286.     return "Surface already has a Device Context.";
  287.     case DDERR_DIRECTDRAWALREADYCREATED:
  288.     return "DirectDraw already bound to this process.";
  289.     case DDERR_EXCEPTION:
  290.     return "Unexpected exception.";
  291.     case DDERR_EXCLUSIVEMODEALREADYSET:
  292.     return "Already in exclusive mode.";
  293.     case DDERR_GENERIC:
  294.     return "Undefined";    /* THIS MAKES SENSE!  FUCKING M$ */
  295.  
  296.     case DDERR_HEIGHTALIGN:
  297.     return "Height needs to be aligned.";
  298.     case DDERR_HWNDALREADYSET:
  299.     return "HWND already set for cooperative level.";
  300.     case DDERR_HWNDSUBCLASSED:
  301.     return "HWND has been subclassed.";
  302.     case DDERR_IMPLICITLYCREATED:
  303.     return "Can't restore an implicitly created surface.";
  304.     case DDERR_INCOMPATIBLEPRIMARY:
  305.     return "New params doesn't match existing primary surface.";
  306.     case DDERR_INVALIDCAPS:
  307.     return "Device doesn't have requested capabilities.";
  308.     case DDERR_INVALIDCLIPLIST:
  309.     return "Provided clip-list not supported.";
  310.     case DDERR_INVALIDDIRECTDRAWGUID:
  311.     return "Invalid GUID.";
  312.     case DDERR_INVALIDMODE:
  313.     return "Mode not supported.";
  314.     case DDERR_INVALIDOBJECT:
  315.     return "Invalid object.";
  316.     case DDERR_INVALIDPARAMS:
  317.     return "Invalid params.";
  318.     case DDERR_INVALIDPIXELFORMAT:
  319.     return "Device doesn't support requested pixel format.";
  320.     case DDERR_INVALIDPOSITION:
  321.     return "Overlay position illegal.";
  322.     case DDERR_INVALIDRECT:
  323.     return "Invalid RECT.";
  324.     case DDERR_INVALIDSURFACETYPE:
  325.     return "Wrong type of surface.";
  326.     case DDERR_LOCKEDSURFACES:
  327.     return "Surface locked.";
  328.     case DDERR_NO3D:
  329.     return "No 3d capabilities.";
  330.     case DDERR_NOALPHAHW:
  331.     return "No alpha h/w.";
  332.     case DDERR_NOBLTHW:
  333.     return "No blit h/w.";
  334.     case DDERR_NOCLIPLIST:
  335.     return "No clip-list.";
  336.     case DDERR_NOCLIPPERATTACHED:
  337.     return "No Clipper attached.";
  338.     case DDERR_NOCOLORCONVHW:
  339.     return "No colour-conversion h/w.";
  340.     case DDERR_NOCOLORKEY:
  341.     return "No colour-key.";
  342.  
  343.     case DDERR_NOTLOCKED:
  344.     return "Not locked.";
  345.     case DDERR_NOTPAGELOCKED:
  346.     return "Not page-locked.";
  347.     case DDERR_NOTPALETTIZED:
  348.     return "Not palette-based.";
  349.  
  350.     case DDERR_OUTOFCAPS:
  351.     return "out of caps";
  352.     case DDERR_OUTOFMEMORY:
  353.     return "Out of memory.";
  354.     case DDERR_OUTOFVIDEOMEMORY:
  355.     return "out of video memory.";
  356.     case DDERR_PALETTEBUSY:
  357.     return "Palette busy.";
  358.     case DDERR_PRIMARYSURFACEALREADYEXISTS:
  359.     return "Already a primary surface.";
  360.  
  361.     case DDERR_SURFACEBUSY:
  362.     return "Surface busy.";
  363.     /*case DDERR_SURFACEOBSCURED:     return "Surface is obscured.";*/
  364.     case DDERR_SURFACELOST:
  365.     return "Surface lost.";
  366.  
  367.     case DDERR_UNSUPPORTED:
  368.     return "Unsupported.";
  369.     case DDERR_UNSUPPORTEDFORMAT:
  370.     return "Unsupported format.";
  371.  
  372.     case DDERR_WASSTILLDRAWING:
  373.     return "Was still drawing.";
  374.     }
  375.     return "";
  376. }
  377.  
  378. static int lockcnt = 0;
  379.  
  380. static int do_surfacelock (void)
  381. {
  382.     HRESULT ddrval = IDirectDrawSurface_Lock (lpDDS, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  383.     if (ddrval != DD_OK) {
  384.     if (ddrval == DDERR_SURFACELOST)
  385.         ddrval = IDirectDrawSurface_Restore (lpDDS);
  386.     else if (ddrval != DDERR_SURFACEBUSY)
  387.         MyOutputDebugString ("lpDDS->Lock() failed - %s (%d)\n", getddrname (ddrval), (unsigned short) ddrval);
  388.     return 0;
  389.     }
  390.     lockcnt++;
  391.     return 1;
  392. }
  393.  
  394. void unlockscr (void)
  395. {
  396.     lockcnt--;
  397.     IDirectDrawSurface_Unlock (lpDDS, ddsd.lpSurface);
  398. }
  399.  
  400. static void release_ddraw_stuff (void)
  401. {
  402.     if (lpDD) {
  403.     IDirectDraw_RestoreDisplayMode (lpDD);
  404.     IDirectDraw_SetCooperativeLevel (lpDD, hAmigaWnd, DDSCL_NORMAL);
  405.     }
  406.     if (lpDDC)
  407.     IDirectDrawClipper_Release (lpDDC);
  408.     if (lpDDS)
  409.     IDirectDrawSurface_Release (lpDDS);
  410.     if (lpDDP)
  411.     IDirectDrawPalette_Release (lpDDP);
  412.     if (lpDD)
  413.     IDirectDraw_Release (lpDD);
  414.     lpDDC = 0;
  415.     lpDDS = 0;
  416.     lpDDP = 0;
  417.     lpDD = 0;
  418. }
  419.  
  420. static int set_ddraw (int width, int height, int wantfull, int *pbytes,
  421.               LPPALETTEENTRY pal)
  422. {
  423.     int bits = 8 * *pbytes;
  424.     HRESULT ddrval;
  425.  
  426. #ifdef __GNUC__
  427.     ddrval = (*pDirectDrawCreate) (NULL, &lpDD, NULL);
  428. #else
  429.     ddrval = DirectDrawCreate (NULL, &lpDD, NULL);
  430. #endif
  431.     if (ddrval != DD_OK)
  432.     goto oops;
  433.  
  434.     ddrval = IDirectDraw_SetCooperativeLevel (lpDD, hAmigaWnd,
  435.                            (wantfull
  436.                         ? DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
  437.                         : DDSCL_NORMAL));
  438.     if (ddrval != DD_OK)
  439.     goto oops;
  440.  
  441.     ddrval = IDirectDraw_CreateClipper (lpDD, 0, &lpDDC, NULL);
  442.     if (ddrval != DD_OK) {
  443.     MyOutputDebugString ("DirectDraw error: Clipper unavailable! (%d)\n", ddrval);
  444.     } else {
  445.     if (IDirectDrawClipper_SetHWnd (lpDDC, 0, hAmigaWnd) != DD_OK)
  446.         MyOutputDebugString ("DirectDraw error: Can't attach HWnd!\n");
  447.     }
  448.  
  449.     if (wantfull) {
  450.     ddrval = IDirectDraw_SetDisplayMode (lpDD, width, height, bits);
  451.     if (ddrval != DD_OK)
  452.         goto oops;
  453.     }
  454.     ddsd.dwSize = sizeof (ddsd);
  455.     ddsd.dwFlags = DDSD_CAPS;
  456.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  457.  
  458.     ddrval = IDirectDraw_CreateSurface (lpDD, &ddsd, &lpDDS, NULL);
  459.     if (ddrval != DD_OK)
  460.     goto oops;
  461.  
  462.     if (! do_surfacelock ())
  463.     return 0;
  464.     unlockscr ();
  465.  
  466.     bits = (ddsd.ddpfPixelFormat.dwRGBBitCount + 7) & ~7;
  467.     current_pixbytes = *pbytes = bits >> 3;
  468.  
  469.     if (bits == 8) {
  470.     ddrval = IDirectDraw_CreatePalette (lpDD, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
  471.                          pal,
  472.                          &lpDDP, NULL);
  473.     if (ddrval != DD_OK)
  474.         goto oops;
  475.  
  476.     ddrval = IDirectDrawSurface2_SetPalette (lpDDS, lpDDP);
  477.     if (ddrval != DD_OK)
  478.         goto oops;
  479.     }
  480.     /* Set global values for current width,height */
  481.     current_width  = width;
  482.     current_height = height;
  483.  
  484.     return 1;
  485.  
  486. oops:
  487.     MyOutputDebugString ("DirectDraw initialization failed with %s/%d\n", getddrname (ddrval), ddrval);
  488.     return 0;
  489. }
  490.  
  491. /* Color management */
  492. static int bits_in_mask (unsigned long mask)
  493. {
  494.     int n = 0;
  495.     while (mask) {
  496.     n += mask & 1;
  497.     mask >>= 1;
  498.     }
  499.     return n;
  500. }
  501.  
  502. static int mask_shift (unsigned long mask)
  503. {
  504.     int n = 0;
  505.     while (!(mask & 1)) {
  506.     n++;
  507.     mask >>= 1;
  508.     }
  509.     return n;
  510. }
  511.  
  512. static xcolnr xcol8[4096];
  513. static PALETTEENTRY colors256[256];
  514. static int ncols256 = 0;
  515.  
  516. static int get_color (int r, int g, int b, xcolnr *cnp)
  517. {
  518.     if (ncols256 == 256)
  519.     return 0;
  520.     colors256[ncols256].peRed = r * 0x11;
  521.     colors256[ncols256].peGreen = g * 0x11;
  522.     colors256[ncols256].peBlue = b * 0x11;
  523.     colors256[ncols256].peFlags = 0;
  524.     *cnp = ncols256;
  525.     ncols256++;
  526.     return 1;
  527. }
  528.  
  529. static void init_colors (void)
  530. {
  531.     if (ncols256 == 0)
  532.     alloc_colors256 (get_color);
  533.     memcpy (xcol8, xcolors, sizeof xcol8);
  534.  
  535.     /* init colors */
  536.  
  537.     switch (current_pixbytes) {
  538.      case 1:
  539.     memcpy (xcolors, xcol8, sizeof xcolors);
  540.     if (lpDDP != 0) {
  541.         HRESULT ddrval = IDirectDrawPalette_SetEntries (lpDDP, 0, 0, 256, colors256);
  542.         if (ddrval != DD_OK)
  543.         MyOutputDebugString ("DX_SetPalette() failed with %s/%d\n", getddrname (ddrval), ddrval);
  544.     }
  545.     break;
  546.  
  547.      case 2:
  548.      case 3:
  549.      case 4:
  550.     {
  551.         int red_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwRBitMask);
  552.         int green_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwGBitMask);
  553.         int blue_bits = bits_in_mask (ddsd.ddpfPixelFormat.dwBBitMask);
  554.         int red_shift = mask_shift (ddsd.ddpfPixelFormat.dwRBitMask);
  555.         int green_shift = mask_shift (ddsd.ddpfPixelFormat.dwGBitMask);
  556.         int blue_shift = mask_shift (ddsd.ddpfPixelFormat.dwBBitMask);
  557.  
  558.         alloc_colors64k (red_bits, green_bits, blue_bits, red_shift,
  559.                  green_shift, blue_shift);
  560.     }
  561.     break;
  562.     }
  563. }
  564.  
  565. static void close_windows (void)
  566. {
  567.     int i;
  568.  
  569.     gfxvidinfo.bufmem = 0;
  570.     gfxvidinfo.linemem = 0;
  571.  
  572.     releasecapture ();
  573.     setmouseactive (0);
  574.     ClipCursor (NULL);
  575.     release_ddraw_stuff ();
  576.  
  577.     if (!hMainWnd && hAmigaWnd) {
  578.     /*ShowWindow (hAmigaWnd, SW_MINIMIZE);*/
  579.     }
  580.     if (hAmigaWnd)
  581.     DestroyWindow (hAmigaWnd);
  582.     if (hMainWnd)
  583.     DestroyWindow (hMainWnd);
  584.     PostQuitMessage (0);
  585.     hMainWnd = 0;
  586.     hAmigaWnd = 0;
  587. }
  588.  
  589. static void destroy_window (int nowait)
  590. {
  591.     if (currprefs.produce_sound > 1)
  592.     stopsound ();
  593.  
  594.     if (!nowait) {
  595.     frame_do_semup = 1;
  596.     set_inhibit_frame (5);
  597.     uae_sem_wait (&frame_sem);
  598.     }
  599.  
  600.     /*SuspendThread (hEmuThread);*/
  601.     close_windows ();
  602. }
  603.  
  604. void displaychange (void)
  605. {
  606.     changemode = 1;
  607.     destroy_window (0);
  608. }
  609.  
  610. void toggle_fullscreen (void)
  611. {
  612.     changemode = 1;
  613.     if (screen_is_picasso)
  614.     picasso_fullscreen ^= 1;
  615.     else
  616.     amiga_fullscreen ^= 1;
  617.     destroy_window (0);
  618. }
  619.  
  620. int can_draw (void)
  621. {
  622.     return gfxvidinfo.pixbytes != 0;
  623. }
  624.  
  625. long FAR PASCAL AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  626. {
  627.     PAINTSTRUCT ps;
  628.     HDC hDC;
  629.  
  630.     if (changemode != 0)
  631.     return DefWindowProc (hWnd, message, wParam, lParam);
  632.  
  633.     switch (message) {
  634.     case WM_ACTIVATEAPP:
  635.     if (bActive = wParam) {
  636.         if (fullscreen) {
  637.         SetCursor (NULL);
  638.         SetCursorPos (mousecx, mousecy);
  639. #ifdef PICASSO96
  640.         if( !picasso96_state.RefreshPending )
  641.             picasso96_state.RefreshPending = 1;
  642. #endif
  643.         }
  644.         my_kbd_handler (VK_CAPITAL, 0x3a, TRUE);
  645.     } else {
  646.         if (!fullscreen)
  647.         setmouseactive (0);
  648.     }
  649.     break;
  650.  
  651.     case WM_ACTIVATE:
  652.     if (LOWORD (wParam) != WA_INACTIVE) {
  653.         ShowWindow (hWnd, SW_RESTORE);
  654.     }
  655.     break;
  656.  
  657.     case WM_SETCURSOR:
  658.     if (fullscreen) {
  659.         SetCursor (NULL);
  660.         return TRUE;
  661.     }
  662.     break;
  663.  
  664.     case WM_SYSCOMMAND:
  665.     if (wParam == SC_ZOOM) {
  666.         toggle_fullscreen ();
  667.         return 0;
  668.     }
  669.     break;
  670.  
  671.     case WM_KEYUP:
  672.     case WM_SYSKEYUP:
  673.     numkeysdown--;
  674.     keysdown[wParam] = 0;
  675.     my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, FALSE);
  676.     break;
  677.  
  678.     case WM_KEYDOWN:
  679.     case WM_SYSKEYDOWN:
  680.     if (LOWORD (lParam) == 1) {
  681.         if (numkeysdown) {
  682.         int key;
  683.         numkeysdown = 0;
  684.  
  685.         for (key = 256; key--;) {
  686.             if (keysdown[key]) {
  687.             if (checkkey (key, lParam))
  688.                 numkeysdown++;
  689.             else {
  690.                 my_kbd_handler (key, (keysdown[key] >> 16) & 0x1ff, FALSE);
  691.                 keysdown[key] = 0;
  692.             }
  693.             }
  694.         }
  695.         }
  696.         if (!keysdown[wParam]) {
  697.         keysdown[wParam] = lParam;
  698.         numkeysdown++;
  699.         }
  700.         numkeysdown++;
  701.         my_kbd_handler (wParam, (lParam >> 16) & 0x1ff, TRUE);
  702.     }
  703.     break;
  704.  
  705.     case WM_LBUTTONDOWN:
  706.     if (ievent_alive) {
  707.         setcapture ();
  708.         buttonstate[0] = 1;
  709.     } else if (!fullscreen && !mouseactive)
  710.         setmouseactive (1);
  711.     else
  712.         buttonstate[0] = 1;
  713.     break;
  714.  
  715.     case WM_LBUTTONUP:
  716.     releasecapture ();
  717.     buttonstate[0] = 0;
  718.     break;
  719.  
  720.     case WM_MBUTTONDOWN:
  721.     if (ievent_alive)
  722.         setcapture ();
  723.     buttonstate[1] = 1;
  724.     break;
  725.  
  726.     case WM_MBUTTONUP:
  727.     releasecapture ();
  728.     buttonstate[1] = 0;
  729.     break;
  730.  
  731.     case WM_RBUTTONDOWN:
  732.     if (ievent_alive)
  733.         setcapture ();
  734.     buttonstate[2] = 1;
  735.     break;
  736.  
  737.     case WM_RBUTTONUP:
  738.     releasecapture ();
  739.     buttonstate[2] = 0;
  740.     break;
  741.  
  742.     case WM_MOUSEMOVE:
  743.     if ((mouseactive && !ievent_alive) || fullscreen) {
  744.         /*
  745.          * In this mode, the mouse pointer is always centered in the window,
  746.          * this is ensured by the SetCursorPos call below.
  747.          * We don't want to handle messages that result from such a SetCursorPos
  748.          * call (recursion!), so exit early if we see one.
  749.          */
  750.         if (lParam == mousecl)
  751.         break;
  752.         lastmx += (signed short) LOWORD (lParam) - mousedx;
  753.         lastmy += (signed short) HIWORD (lParam) - mousedy;
  754.         if (ievent_alive) {
  755.         if (lastmx < 0)
  756.             lastmx = 0;
  757.         if (lastmx > current_width)
  758.             lastmx = current_width;
  759.         if (lastmy < 0)
  760.             lastmy = 0;
  761.         if (lastmy > current_height)
  762.             lastmy = current_height;
  763.  
  764.         }
  765.         SetCursorPos (mousecx, mousecy);
  766.         break;
  767.     }
  768.     lastmx = (signed short) LOWORD (lParam);
  769.     lastmy = (signed short) HIWORD (lParam);
  770.     break;
  771.  
  772.     case WM_PAINT:
  773.     hDC = BeginPaint (hWnd, &ps);
  774.     clear_inhibit_frame (IHF_WINDOWHIDDEN);
  775.     if (hBackDC)
  776.         BitBlt (hDC, ps.rcPaint.left, ps.rcPaint.top,
  777.             ps.rcPaint.right - ps.rcPaint.left,
  778.             ps.rcPaint.bottom - ps.rcPaint.top, hBackDC,
  779.             ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
  780.     else
  781.         notice_screen_contents_lost ();
  782.  
  783.     EndPaint (hWnd, &ps);
  784.     break;
  785.  
  786.     case WM_DROPFILES:
  787.     if (DragQueryFile ((HDROP) wParam, (UINT) - 1, NULL, 0)) {
  788.         if (DragQueryFile ((HDROP) wParam, 0, NULL, 0) < 255)
  789.         DragQueryFile ((HDROP) wParam, 0, changed_prefs.df[0], sizeof (changed_prefs.df[0]));
  790.     }
  791.     DragFinish ((HDROP) wParam);
  792.     break;
  793.  
  794.     case WM_CAPTURECHANGED:
  795.     if (lParam != hWnd)
  796.         buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  797.     break;
  798.  
  799.     case WM_TIMER:
  800. #if 0
  801.     if (wParam == 2) {
  802.         KillTimer (hwnd, timer_id);
  803.         timer_id = 0;
  804.         ClearVisibleAreaAndRefresh ();
  805.     } else
  806. #endif
  807.     {
  808.         finishjob ();
  809.     }
  810.     break;
  811.  
  812.     case WM_USER + 0x200:
  813.     DoSomeWeirdPrintingStuff(wParam);
  814.     break;
  815.  
  816.     case WM_USER + 0x201:
  817.     changemode = 2;
  818.     destroy_window (1);
  819.     break;
  820.  
  821.     case WM_CREATE:
  822.     DragAcceptFiles (hWnd, TRUE);
  823.     break;
  824.  
  825.     case WM_DESTROY:
  826.     changemode = 3;
  827.     destroy_window (0);
  828.     break;
  829.     }
  830.  
  831.     return DefWindowProc (hWnd, message, wParam, lParam);
  832. }
  833.  
  834. long FAR PASCAL MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  835. {
  836.     PAINTSTRUCT ps;
  837.     RECT rc, rc2;
  838.     HDC hDC;
  839.  
  840.     if (changemode != 0)
  841.     return DefWindowProc (hWnd, message, wParam, lParam);
  842.  
  843.     switch (message) {
  844.      case WM_LBUTTONDOWN:
  845.      case WM_MOUSEMOVE:
  846.      case WM_ACTIVATEAPP:
  847.      case WM_ACTIVATE:
  848.      case WM_SETCURSOR:
  849.      case WM_SYSCOMMAND:
  850.      case WM_KEYUP:
  851.      case WM_SYSKEYUP:
  852.      case WM_KEYDOWN:
  853.      case WM_SYSKEYDOWN:
  854.      case WM_LBUTTONUP:
  855.      case WM_MBUTTONDOWN:
  856.      case WM_MBUTTONUP:
  857.      case WM_RBUTTONDOWN:
  858.      case WM_RBUTTONUP:
  859.      case WM_DROPFILES:
  860.      case WM_CREATE:
  861.      case WM_DESTROY:
  862.      case WM_USER + 0x200:
  863.      case WM_USER + 0x201:
  864.     return AmigaWindowProc (hWnd, message, wParam, lParam);
  865.  
  866.      case WM_DISPLAYCHANGE:
  867.     if (!fullscreen && !changemode && (wParam + 7) / 8 != current_pixbytes)
  868.         displaychange ();
  869.     break;
  870.  
  871.      case WM_ENTERSIZEMOVE:
  872.     if (!fullscreen) {
  873.         frame_do_semup = 1;
  874.         set_inhibit_frame (5);
  875.         uae_sem_wait (&frame_sem);
  876.     }
  877.     break;
  878.  
  879.      case WM_EXITSIZEMOVE:
  880.     clear_inhibit_frame (5);
  881.     /* fall through */
  882.  
  883.      case WM_WINDOWPOSCHANGED:
  884.     GetWindowRect (hAmigaWnd, &amigawin_rect);
  885.  
  886.     if (!fullscreen && hAmigaWnd) {
  887.         if (current_pixbytes == 2) {
  888.         if (amigawin_rect.left & 1) {
  889.             GetWindowRect (hMainWnd, &rc2);
  890.             if (1 /*!mon || rc2.left + 4 < GetSystemMetrics (SM_CXSCREEN)*/)
  891.             MoveWindow (hMainWnd, rc2.left + 1, rc2.top,
  892.                     rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
  893.         }
  894.         } else if (current_pixbytes == 3) {
  895.         if (amigawin_rect.left >= 0) {
  896.             if (amigawin_rect.left & 3) {
  897.             GetWindowRect (hMainWnd, &rc2);
  898.             if (1 /*!mon || rc2.left + 4 < GetSystemMetrics (SM_CXSCREEN)*/)
  899.                 MoveWindow (hMainWnd, rc2.left - amigawin_rect.left % 4, rc2.top,
  900.                     rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
  901.             }
  902.         }
  903.         }
  904.         setmouseactive (0);
  905.         return 0;
  906.     }
  907.     break;
  908.  
  909.      case WM_PAINT:
  910.     hDC = BeginPaint (hWnd, &ps);
  911.     GetClientRect (hWnd, &rc);
  912.     DrawEdge (hDC, &rc, EDGE_SUNKEN, BF_RECT);
  913.  
  914.     EndPaint (hWnd, &ps);
  915.     break;
  916.  
  917.      case WM_NCLBUTTONDBLCLK:
  918.     if (wParam == HTCAPTION) {
  919.         toggle_fullscreen ();
  920.         return 0;
  921.     }
  922.     }
  923.  
  924.     return DefWindowProc (hWnd, message, wParam, lParam);
  925. }
  926.  
  927. static int HasConsole;
  928. static HANDLE stdouthandle;
  929. static HANDLE debugfile;
  930.  
  931. /* Console Win32 helper routines */
  932. void activate_debugger ();
  933.  
  934. static BOOL __stdcall ctrlchandler (DWORD type)
  935. {
  936.     SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, FALSE);
  937.  
  938.     if (type == CTRL_C_EVENT) {
  939.     activate_debugger ();
  940.     return TRUE;
  941.     }
  942.     return FALSE;
  943. }
  944.  
  945. void setup_brkhandler (void)
  946. {
  947.     SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, TRUE);
  948. }
  949.  
  950. void remove_brkhandler (void)
  951. {
  952.     SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrlchandler, FALSE);
  953. }
  954.  
  955. int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  956.             int nCmdShow)
  957. {
  958.     char *posn;
  959.     int i;
  960.  
  961.     hInst = hInstance;
  962.  
  963.     debugfile = CreateFile ("outfile", GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
  964.                 0, NULL);
  965.  
  966.     for (i = 0; i < NUM_DRIVES; i++) {
  967.     drives[i].path[0] = 0;
  968.     drives[i].name[0] = 0;
  969.     drives[i].rw = TRUE;
  970.     }
  971.  
  972.     /* Get our executable's root-path */
  973.     start_path = xmalloc(MAX_PATH);
  974.     GetModuleFileName (hInst, start_path, MAX_PATH);
  975.     if (posn = strrchr (start_path, '\\'))
  976.     *posn = 0;
  977.  
  978.  
  979.     HasConsole = 0;/*AllocConsole ();*/
  980.     if (HasConsole)
  981.     stdouthandle = GetStdHandle (STD_OUTPUT_HANDLE);
  982.  
  983.     write_log ("UAE " UAEWINVERSION " Win32/DirectX, release " UAEWINRELEASE "\n");
  984.     strcpy (VersionStr, PROGNAME);
  985.     write_log ("\n(c) 1995-1997 Bernd Schmidt   - Core UAE concept and implementation."
  986.            "\n(c) 1996-1997 Mathias Ortmann - Win32 port and enhancements."
  987.            "\n(c) 1996-1997 Brian King      - Picasso96 and AHI support, GUI.\n"
  988.            "\nPress F12 to show the Settings Dialog (GUI), Alt-F4 to quit.\n"
  989.            "\nhttp://www.informatik.tu-muenchen.de/~ortmann/uae/\n\n");
  990.  
  991.     currprefs.copper_pos = -1;
  992.     /*initgfxspecs();*/
  993.     if (initlibs ())
  994.     real_main (__argc, __argv);
  995.     cleanuplibs();
  996.  
  997.     if (HasConsole)
  998.     FreeConsole ();
  999.  
  1000.     return FALSE;
  1001. }
  1002.  
  1003. static int register_classes (void)
  1004. {
  1005.     WNDCLASS wc;
  1006.  
  1007.     wc.style = 0;
  1008.     wc.lpfnWndProc = AmigaWindowProc;
  1009.     wc.cbClsExtra = 0;
  1010.     wc.cbWndExtra = 0;
  1011.     wc.hInstance = 0;
  1012.     wc.hIcon = LoadIcon (GetModuleHandle (NULL), IDI_APPICON);
  1013.     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  1014.     wc.hbrBackground = GetStockObject (BLACK_BRUSH);
  1015.     wc.lpszMenuName = NULL;
  1016.     wc.lpszClassName = "AmigaPowah";
  1017.     if (!RegisterClass (&wc))
  1018.     return 0;
  1019.  
  1020.     wc.style = 0;
  1021.     wc.lpfnWndProc = MainWindowProc;
  1022.     wc.cbClsExtra = 0;
  1023.     wc.cbWndExtra = 0;
  1024.     wc.hInstance = 0;
  1025.     wc.hIcon = LoadIcon (GetModuleHandle (NULL), IDI_APPICON);
  1026.     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  1027.     wc.hbrBackground = GetStockObject (BLACK_BRUSH);
  1028.     wc.lpszMenuName = NULL;
  1029.     wc.lpszClassName = "PCsuxRox";
  1030.     if (!RegisterClass (&wc))
  1031.     return 0;
  1032.     return 1;
  1033. }
  1034.  
  1035. int graphics_setup (void)
  1036. {
  1037.     DWORD ddrval;
  1038.  
  1039.     if (!register_classes ())
  1040.     return 0;
  1041.  
  1042.     uae_sem_init (&picasso_switch_sem, 0, 0);
  1043.     return 1;
  1044. }
  1045.  
  1046. #define NORMAL_WINDOW_STYLE (WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
  1047.  
  1048. static int create_windows (void)
  1049. {
  1050.     POINT pt;
  1051.  
  1052.     if (!fullscreen) {
  1053.     RECT rc;
  1054.  
  1055.     rc.left = 0;
  1056.     rc.top = 0;
  1057.     rc.right = current_width;
  1058.     rc.bottom = current_height;
  1059.     rc.right += 4;
  1060.     rc.bottom += 4;
  1061.     AdjustWindowRect (&rc, NORMAL_WINDOW_STYLE, FALSE);
  1062.  
  1063.     hMainWnd = CreateWindowEx (WS_EX_ACCEPTFILES,
  1064.                    "PCsuxRox",
  1065.                    TITLETEXT,
  1066.                    NORMAL_WINDOW_STYLE,
  1067.                    CW_USEDEFAULT, CW_USEDEFAULT,
  1068.                    rc.right - rc.left, rc.bottom - rc.top,
  1069.                    NULL,
  1070.                    NULL,
  1071.                    0,
  1072.                    NULL);
  1073.  
  1074.     if (! hMainWnd)
  1075.         return 0;
  1076.     } else
  1077.     hMainWnd = NULL;
  1078.  
  1079.     hAmigaWnd = CreateWindowEx (fullscreen ? WS_EX_TOPMOST : WS_EX_ACCEPTFILES,
  1080.                 "AmigaPowah",
  1081.                 PROGNAME,
  1082.                 hMainWnd ? WS_VISIBLE | WS_CHILD : WS_VISIBLE | WS_POPUP,
  1083.                 hMainWnd ? 2 : CW_USEDEFAULT, hMainWnd ? 2 : CW_USEDEFAULT,
  1084.                 fullscreen ? GetSystemMetrics (SM_CXSCREEN) : current_width,
  1085.                 fullscreen ? GetSystemMetrics (SM_CYSCREEN) : current_height,
  1086.                 hMainWnd,
  1087.                 NULL,
  1088.                 0,
  1089.                 NULL);
  1090.  
  1091.     if (!hAmigaWnd) {
  1092.     if (hMainWnd)
  1093.         DestroyWindow (hMainWnd);
  1094.     return 0;
  1095.     }
  1096.  
  1097.     if (hMainWnd)
  1098.     UpdateWindow (hMainWnd);
  1099.     if (hAmigaWnd)
  1100.     UpdateWindow (hAmigaWnd);
  1101.  
  1102.     return 1;
  1103. }
  1104.  
  1105. void doPreInit( void )
  1106. {
  1107.     void *blah;
  1108.     DWORD ddrval;
  1109. #ifdef __GNUC__
  1110.     ddrval = (*pDirectDrawCreate)(NULL,&lpDD,NULL);
  1111. #else
  1112.     ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  1113. #endif
  1114.     if (ddrval == DD_OK)
  1115.     {
  1116.         //IDirectDraw2_QueryInterface( lpDD, &IID_IDirectDraw2, &blah );
  1117.  
  1118.         mode_count = DX_FillResolutions( &picasso96_pixel_format );
  1119.  
  1120.         // If we've got no command-line arguments, then we use the integrated-GUI
  1121.         if( ( __argc == 1 ) && 
  1122.             ( GetSettings() == FALSE ) )
  1123.         {
  1124.             MyOutputDebugString("GetSettings() trying to quit...\n"); 
  1125.             shutdownmain();
  1126.         }
  1127.     }
  1128. }
  1129.  
  1130. BOOL doInit (void)
  1131. {
  1132.     if (! create_windows ())
  1133.     return 0;
  1134. #ifdef PICASSO96
  1135.     if (screen_is_picasso) {
  1136.     if (!set_ddraw (current_width, current_height, fullscreen, &picasso_vidinfo.depth,
  1137.             (LPPALETTEENTRY)&picasso96_state.CLUT))
  1138.         goto oops;
  1139.     picasso_vidinfo.rowbytes = ddsd.lPitch;
  1140.     } else
  1141. #endif
  1142.     {
  1143.     gfxvidinfo.pixbytes = 2;
  1144.     if (!set_ddraw (current_width, current_height, fullscreen, &gfxvidinfo.pixbytes, colors256))
  1145.         goto oops;
  1146.     gfxvidinfo.bufmem = 0;
  1147.     gfxvidinfo.linemem = 0;
  1148.     gfxvidinfo.maxblocklines = 0;
  1149.     gfxvidinfo.width = current_width;
  1150.     gfxvidinfo.height = current_height;
  1151.     gfxvidinfo.rowbytes = ddsd.lPitch;
  1152.     gfxvidinfo.can_double = 1;
  1153.     }
  1154.  
  1155.     if (fullscreen) {
  1156.     scrindirect = 0;
  1157.     gfxvidinfo.linemem = 0;
  1158.     mousecx = 160, mousecy = 100, mousedx = 160, mousedy = 100, mousecl = MAKELONG (160, 100);
  1159.     }
  1160.  
  1161.     if (! do_surfacelock ())
  1162.     goto oops;
  1163.     unlockscr ();
  1164.  
  1165.     if ((ddsd.ddpfPixelFormat.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8 | DDPF_RGBTOYUV)) != 0)
  1166.     {
  1167.     MyOutputDebugString ("%s mode (bits: %d, pixbytes: %d)\n", fullscreen ? "Full screen" : "Window",
  1168.                  ddsd.ddpfPixelFormat.dwRGBBitCount, current_pixbytes);
  1169. #ifdef PICASSO96
  1170.             if( ddsd.ddpfPixelFormat.dwRBitMask == 0x0000F800 )
  1171.                 picasso96_pixel_format |= RGBFF_R5G6B5PC;
  1172.             else if( ddsd.ddpfPixelFormat.dwRBitMask == 0x00007C00 )
  1173.                 picasso96_pixel_format |= RGBFF_R5G5B5PC;
  1174.             else if( ddsd.ddpfPixelFormat.dwBBitMask == 0x0000F800 )
  1175.                 picasso96_pixel_format |= RGBFF_B5G6R5PC;
  1176.             else
  1177.                 picasso96_pixel_format |= RGBFF_B5G5R5PC;
  1178. #endif
  1179.     } else {
  1180.     MyOutputDebugString ("Error: Unsupported pixel format - use a different screen mode\n");
  1181.     goto oops;
  1182.     }
  1183. #ifdef PICASSO96
  1184.     if (screen_is_picasso)
  1185.     DX_SetPalette (0, 256);
  1186.     else
  1187. #endif
  1188.     init_colors ();
  1189.  
  1190.     if (!fullscreen)
  1191.     MainWindowProc (0, WM_WINDOWPOSCHANGED, 0, 0);
  1192.     return 1;
  1193.  
  1194. oops:
  1195.     if (hMainWnd)
  1196.     DestroyWindow (hMainWnd);
  1197.     if (hAmigaWnd)
  1198.     DestroyWindow (hAmigaWnd);
  1199.     return 0;
  1200. }
  1201.  
  1202. struct myRGNDATA {
  1203.     RGNDATAHEADER rdh;
  1204.     RECT rects[640];    /* fixed buffers suck, but this is _very_ unlikely to overflow */
  1205. } ClipList = { {
  1206.     sizeof (ClipList), RDH_RECTANGLES, 0, 640 * sizeof (RECT)
  1207. } };
  1208.  
  1209.  
  1210. /* this is the way the display line is put to screen
  1211.  * if the display is not 16 bits deep or the window is not fully visible */
  1212. static void clipped_linetoscr (char *dst, char *src, int y)
  1213. {
  1214.     LPRECT lpRect = ClipList.rects;
  1215.     int i;
  1216.  
  1217.     switch (current_pixbytes) {
  1218.     case 1:
  1219.     for (i = ClipList.rdh.nCount; i--; lpRect++) {
  1220.         if (y >= lpRect->top && y < lpRect->bottom) {
  1221.         memcpy (dst + lpRect->left, src + lpRect->left, lpRect->right);
  1222.         }
  1223.     }
  1224.     break;
  1225.  
  1226.     case 2:
  1227.     for (i = ClipList.rdh.nCount; i--; lpRect++) {
  1228.         if (y >= lpRect->top && y < lpRect->bottom) {
  1229.         memcpy (dst + lpRect->left*2, src + lpRect->left*2, lpRect->right*2);
  1230.         }
  1231.     }
  1232.     break;
  1233.  
  1234.     case 3:
  1235.     for (i = ClipList.rdh.nCount; i--; lpRect++) {
  1236.         if (y >= lpRect->top && y < lpRect->bottom) {
  1237.         memcpy (dst + lpRect->left*3, src + lpRect->left*3, lpRect->right*3);
  1238.         }
  1239.     }
  1240.     break;
  1241.  
  1242.      case 4:
  1243.     for (i = ClipList.rdh.nCount; i--; lpRect++) {
  1244.         if (y >= lpRect->top && y < lpRect->bottom) {
  1245.         memcpy (dst + lpRect->left*4, src + lpRect->left*4, lpRect->right*4);
  1246.         }
  1247.     }
  1248.     break;
  1249.     }
  1250. }
  1251.  
  1252. void flush_line(int lineno)
  1253. {
  1254.     if (scrindirect)
  1255.     clipped_linetoscr(gfxvidinfo.bufmem + lineno * gfxvidinfo.rowbytes,
  1256.               scrlinebuf, lineno);
  1257. }
  1258.  
  1259. void flush_block(int a, int b)
  1260. {
  1261. }
  1262.  
  1263. void flush_screen(int a, int b)
  1264. {
  1265. }
  1266.  
  1267. char *lockscr (void)
  1268. {
  1269.     char *surface, *oldsurface;
  1270.     DWORD tmp;
  1271.     LPRECT lpRect;
  1272.  
  1273.     if (!do_surfacelock ())
  1274.     return NULL;
  1275.  
  1276.     surface = ddsd.lpSurface;
  1277.     oldsurface = gfxvidinfo.bufmem;
  1278.     if (!fullscreen) {
  1279.     surface += amigawin_rect.top * ddsd.lPitch + current_pixbytes * amigawin_rect.left;
  1280.     }
  1281.     gfxvidinfo.bufmem = surface;
  1282.     if (surface != oldsurface && ! screen_is_picasso) {
  1283.     write_log ("Need to init_row_map\n");
  1284.     init_row_map ();
  1285.     }
  1286.  
  1287.     scrindirect = 0;
  1288.  
  1289.     if (fullscreen) {
  1290.     set_linemem ();
  1291.     clear_inhibit_frame (IHF_WINDOWHIDDEN);
  1292.     return surface;
  1293.     }
  1294.  
  1295.     tmp = sizeof (ClipList.rects);
  1296.  
  1297.     /* This is the VERY instruction that drags other threads (input/file system) down when in windowed
  1298.      * mode - WHY can't Microsoft implement the IsClipListChanged() method as documented? ARGH! */
  1299.     if (IDirectDrawClipper_GetClipList (lpDDC, NULL, (LPRGNDATA) & ClipList, &tmp) == DD_OK) {
  1300.     lpRect = ClipList.rects;
  1301.  
  1302.     if (!ClipList.rdh.nCount) {
  1303.         write_log("ClipList empty\n");
  1304.         set_inhibit_frame (IHF_WINDOWHIDDEN);
  1305.         unlockscr ();
  1306.         return 0;
  1307.     }
  1308.  
  1309.     if (ClipList.rdh.nCount != 1
  1310.         || lpRect->right - lpRect->left != current_width
  1311.         || lpRect->bottom - lpRect->top != current_height)
  1312.     {
  1313.         scrindirect = 1;
  1314.         for (tmp = ClipList.rdh.nCount; tmp--; lpRect++) {
  1315.         lpRect->left -= amigawin_rect.left;
  1316.         lpRect->right -= amigawin_rect.left;
  1317.         lpRect->top -= amigawin_rect.top;
  1318.         lpRect->bottom -= amigawin_rect.top;
  1319.  
  1320.         lpRect->right -= lpRect->left;
  1321.         }
  1322.     }
  1323.     }
  1324.  
  1325.     set_linemem ();
  1326.     clear_inhibit_frame (IHF_WINDOWHIDDEN);
  1327.     return surface;
  1328. }
  1329.  
  1330. int graphics_init (void)
  1331. {
  1332.     static int first_time = 1;
  1333.     if (first_time)
  1334.     figure_processor_speed ();
  1335.     first_time = 0;
  1336. #ifdef PICASSO96
  1337.     if (screen_is_picasso) {
  1338.     fullscreen = picasso_fullscreen;
  1339.     current_width = picasso_vidinfo.width;
  1340.     current_height = picasso_vidinfo.height;
  1341.     } else 
  1342. #endif
  1343.     {
  1344.     fullscreen = amiga_fullscreen;
  1345.     current_width = currprefs.gfx_width;
  1346.     current_height = currprefs.gfx_height;
  1347.  
  1348.     if (!fullscreen) {
  1349.         if (current_height > 290 << currprefs.gfx_linedbl)
  1350.         current_height = 290 << currprefs.gfx_linedbl;
  1351.         if (current_width > 800 >> currprefs.gfx_lores)
  1352.         current_width = 800 >> currprefs.gfx_lores;
  1353.     }
  1354.     current_width = (current_width + 7) & ~7;
  1355.     }
  1356.  
  1357.     if (!doInit ())
  1358.     return 0;
  1359.  
  1360.     *xcolors = 0;
  1361.  
  1362.     return 1;
  1363. }
  1364.  
  1365. void graphics_leave (void)
  1366. {
  1367.     dumpcustom ();
  1368. }
  1369.  
  1370. void shutdownmain (void)
  1371. {
  1372.     changemode = 3;
  1373.     PostMessage (hAmigaWnd, WM_QUIT, 0, 0);
  1374. }
  1375.  
  1376. void workthread(void)
  1377. {
  1378.     if (use_debugger && debuggable ())
  1379.     activate_debugger ();
  1380.  
  1381.     do_start_program();
  1382.     shutdownmain();
  1383. }
  1384.  
  1385. void start_program (void)
  1386. {
  1387.     DWORD id;
  1388.     MSG msg;
  1389.  
  1390.     SetPriorityClass (GetCurrentProcess (), process_desired_pri);
  1391.  
  1392.     hEmuThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) workthread, 0, CREATE_SUSPENDED, &id);
  1393.     SetThreadPriority (hEmuThread, THREAD_PRIORITY_BELOW_NORMAL);
  1394.     ResumeThread (hEmuThread);
  1395.  
  1396.     for (;;) {
  1397.     int cm;
  1398.     while (GetMessage (&msg, NULL, 0, 0)) {
  1399.         TranslateMessage (&msg);
  1400.         DispatchMessage (&msg);
  1401.     }
  1402.     cm = changemode;
  1403.     if (cm == 3)
  1404.         break;
  1405.  
  1406.     changemode = 0;
  1407.     current_pixbytes = 0;
  1408.     if (!graphics_init ())
  1409.         break;
  1410.  
  1411.     if (cm == 2) {
  1412.         uae_sem_post (&picasso_switch_sem);
  1413.     }
  1414.     clear_inhibit_frame (5);
  1415.     notice_screen_contents_lost ();
  1416.     notice_new_xcolors ();
  1417.  
  1418.     notice_new_xcolors ();
  1419.  
  1420.     /*ResumeThread (hEmuThread);*/
  1421.  
  1422.     if (currprefs.produce_sound > 1)
  1423.         startsound ();
  1424.     }
  1425. }
  1426.  
  1427. void handle_events (void)
  1428. {
  1429. }
  1430.  
  1431. #ifdef CONFIG_FOR_SMP
  1432. int uae_sem_initcs (LPCRITICAL_SECTION * cs)
  1433. {
  1434.     *cs = (LPCRITICAL_SECTION) GlobalAlloc (GPTR, sizeof csDraw);
  1435.     InitializeCriticalSection (*cs);
  1436. }
  1437.  
  1438. void uae_sem_enter (LPCRITICAL_SECTION cs)
  1439. {
  1440.     EnterCriticalSection (cs);
  1441. }
  1442.  
  1443. void uae_sem_leave (LPCRITICAL_SECTION cs)
  1444. {
  1445.     LeaveCriticalSection (cs);
  1446. }
  1447.  
  1448. void uae_sleep (int ms)
  1449. {
  1450.     Sleep (ms);
  1451. }
  1452.  
  1453. #endif
  1454.  
  1455. /* this is the semaphore for protecting the actual drawing against intermittent window movements */
  1456. void begindrawing (void)
  1457. {
  1458.     EnterCriticalSection (&csDraw);
  1459. }
  1460.  
  1461. void enddrawing (void)
  1462. {
  1463.     LeaveCriticalSection (&csDraw);
  1464. }
  1465.  
  1466. /* this truly sucks, I'll include a native gunzip() routine soon */
  1467. int gunzip_hack (const char *src, const char *dst)
  1468. {
  1469.     char buf[1024];
  1470.     STARTUPINFO si =
  1471.     {sizeof si};
  1472.     PROCESS_INFORMATION pi;
  1473.  
  1474.     strcpy (buf, dst);
  1475.     strcat (buf, ".gz");
  1476.  
  1477.     if (CopyFile (src, buf, FALSE)) {
  1478.     sprintf (buf, "gzip -f -d \"%s.gz\"", dst);
  1479.     si.dwFlags = STARTF_USESTDHANDLES;
  1480.     if (CreateProcess (NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
  1481.         WaitForSingleObject (pi.hProcess, INFINITE);
  1482.         return -1;
  1483.     } else {
  1484.         MyOutputDebugString ("Error: You need gzip.exe (32 bit) to use .adz/.roz files!\n");
  1485.     }
  1486.     }
  1487.     return 0;
  1488. }
  1489.  
  1490. /* file name requester. hBackBM will hopefully be dropped in the near future. */
  1491. static OPENFILENAME ofn = {
  1492.     sizeof (OPENFILENAME),
  1493.     NULL, NULL, "Amiga Disk Files\000*.adf;*.adz\000",
  1494.     NULL, 0, 0, 0, 256, NULL, 0, "",
  1495.     0,
  1496.     OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  1497.     0,
  1498.     0,
  1499.     "adf",
  1500.     0,
  1501.     NULL,
  1502.     NULL
  1503. };
  1504.  
  1505. int requestfname (char *title, char *name)
  1506. {
  1507.     HDC hDC;
  1508.     char *result;
  1509.     RECT rc;
  1510. #ifdef PICASSO96
  1511.     uae_u8 old_switch_state = picasso96_state.SwitchState;
  1512. #endif
  1513.  
  1514.     ofn.hwndOwner = hAmigaWnd;
  1515.     ofn.lpstrTitle = title;
  1516.     ofn.lpstrFile = name;
  1517.  
  1518.     if (pGetOpenFileNameA == 0)
  1519.     return 0;
  1520.  
  1521.     if (IDirectDrawSurface_GetDC (lpDDS, &hDC) == DD_OK) {
  1522.     if ((hBackBM = CreateCompatibleBitmap (hDC, currprefs.gfx_width, currprefs.gfx_height))
  1523.         && (hBackDC = CreateCompatibleDC (hDC))) {
  1524.         SelectObject (hBackDC, hBackBM);
  1525.  
  1526.         if (fullscreen)
  1527.         BitBlt (hBackDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hDC, 0, 0, SRCCOPY);
  1528.         else {
  1529.         BitBlt (hBackDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hDC,
  1530.             amigawin_rect.left, amigawin_rect.top, SRCCOPY);
  1531.         }
  1532.     }
  1533.     IDirectDrawSurface_ReleaseDC (lpDDS, hDC);
  1534.     }
  1535.     if (!fullscreen)
  1536.     setmouseactive (0);
  1537.  
  1538.     if (title)
  1539.     result = (char *)((*pGetOpenFileNameA) (&ofn));
  1540.     else {
  1541.     GetSettings ();
  1542.     }
  1543.  
  1544.     if (!fullscreen || !mouseactive)
  1545.     SetCursor (NULL);
  1546.  
  1547.     if (hBackBM) {
  1548.     if (hBackDC) {
  1549.         if (fullscreen && IDirectDrawSurface_GetDC (lpDDS, &hDC) == DD_OK) {
  1550.         BitBlt (hDC, 0, 0, currprefs.gfx_width, currprefs.gfx_height, hBackDC, 0, 0, SRCCOPY);
  1551.         IDirectDrawSurface_ReleaseDC (lpDDS, hDC);
  1552.         }
  1553.         DeleteObject (hBackDC);
  1554.         hBackDC = NULL;
  1555.     }
  1556.     DeleteObject (hBackBM);
  1557.     hBackBM = NULL;
  1558.     }
  1559.     notice_screen_contents_lost ();
  1560.  
  1561.     if (result)
  1562.     return 1;
  1563.  
  1564.     return 0;
  1565. }
  1566.  
  1567. int DisplayGUI( void )
  1568. {
  1569.     HBITMAP hBackBM2 = NULL;
  1570. #ifdef PICASSO96
  1571.     BITMAPINFO bminfo = { sizeof( BITMAPINFOHEADER ), current_width, -current_height, 1, 8, BI_RGB, 0, 0, 0, 0, 0, &picasso96_state.CLUT };
  1572. #endif
  1573.     HDC hDC;
  1574.     void *blah;
  1575.     RECT rc;
  1576.     uae_u8 p96_8bit = 0;
  1577.  
  1578.     if (pGetOpenFileNameA)
  1579.     {
  1580.         if (IDirectDrawSurface_GetDC(lpDDS,&hDC) == DD_OK)
  1581.         {
  1582. #ifdef PICASSO96
  1583.             if( picasso96_state.SwitchState && ( picasso96_state.BytesPerPixel == 1 ) )
  1584.             {
  1585.                 p96_8bit = 1;
  1586.                 hBackBM2 = CreateDIBSection( hDC, &bminfo, DIB_PAL_COLORS, &blah, NULL, 0 );
  1587.             }
  1588.             else
  1589. #endif
  1590.                 hBackBM = CreateCompatibleBitmap( hDC, current_width, current_height );
  1591.  
  1592.             if( (hBackBM2 || hBackBM ) && ( hBackDC = CreateCompatibleDC( hDC ) ) )
  1593.             {
  1594. #ifdef PICASSO96
  1595.                 if( hBackBM2 )
  1596.                 {
  1597.                     SelectObject( hBackDC, hBackBM2 );
  1598.                     hBackBM = CreateCompatibleBitmap( hDC, current_width, current_height );
  1599.                 }
  1600.                 else
  1601. #endif
  1602.                     SelectObject( hBackDC, hBackBM );
  1603.  
  1604.                 if( fullscreen ) 
  1605.                     BitBlt( hBackDC, 0, 0, current_width, current_height, hDC, 0, 0, SRCCOPY );
  1606.                 else
  1607.                 {
  1608.                     GetWindowRect(hAmigaWnd,&rc);
  1609.                     BitBlt(hBackDC,0,0,current_width,current_height,hDC,rc.left,rc.top,SRCCOPY);
  1610.                 }
  1611.  
  1612.                 IDirectDrawSurface2_SetPalette( lpDDS, NULL );
  1613.                 if( hBackBM2 )
  1614.                     BitBlt( hDC, 0, 0, current_width, current_height, hBackDC, 0, 0, SRCCOPY );
  1615.             }
  1616.             IDirectDrawSurface_ReleaseDC( lpDDS, hDC );
  1617.         }
  1618.  
  1619.         if (!fullscreen) setmouseactive(FALSE);
  1620.  
  1621.         GetSettings();
  1622.         if( lpDDP )
  1623.             IDirectDrawSurface2_SetPalette( lpDDS, lpDDP );
  1624.     
  1625.         if (!fullscreen || !mouseactive) SetCursor(NULL);
  1626.  
  1627.         if( hBackBM || hBackBM2 )
  1628.         {
  1629.             if( hBackDC )
  1630.             {
  1631. #ifdef PICASSO96
  1632.                 if( p96_8bit )
  1633.                 {
  1634.                     picasso96_state.RefreshPending = 1;
  1635.                 }
  1636.                 else
  1637. #endif
  1638.                 if( fullscreen && IDirectDrawSurface_GetDC( lpDDS, &hDC ) == DD_OK )
  1639.                 {
  1640.                     BitBlt( hDC, 0, 0, current_width, current_height, hBackDC, 0, 0, SRCCOPY );
  1641.                     IDirectDrawSurface_ReleaseDC( lpDDS, hDC );
  1642.                 }
  1643.                 DeleteObject( hBackDC );
  1644.                 hBackDC = NULL;
  1645.             }
  1646.             if( hBackBM2 )
  1647.                 DeleteObject( hBackBM2 );
  1648.             if( hBackBM )
  1649.             {
  1650.                 DeleteObject( hBackBM );
  1651.                 hBackBM = NULL;
  1652.             }
  1653.         }
  1654.     }
  1655.     return 0;
  1656. }
  1657.  
  1658. #ifdef __GNUC__
  1659. #undef WINAPI
  1660. #define WINAPI
  1661. #endif
  1662.  
  1663. static HINSTANCE hDDraw = NULL, hComDlg32 = NULL, hRichEdit = NULL;
  1664.  
  1665. int cleanuplibs(void)
  1666. {
  1667.     if (hRichEdit)
  1668.     FreeLibrary(hRichEdit);
  1669.     if (hDDraw)
  1670.     FreeLibrary(hDDraw);
  1671.     if (hComDlg32)
  1672.     FreeLibrary(hComDlg32);
  1673.     return 1;
  1674. }
  1675.  
  1676. /* try to load COMDLG32 and DDRAW, initialize csDraw, try to obtain the system clock frequency
  1677.  * from the registry, try to find out if we are running on a Pentium */
  1678. int initlibs (void)
  1679. {
  1680.     /* Make sure we do an InitCommonControls() to get some advanced controls */
  1681.     InitCommonControls ();
  1682.  
  1683.     if (hComDlg32 = LoadLibrary ("COMDLG32.DLL")) {
  1684.     pGetOpenFileNameA = (BOOL (WINAPI *) (LPOPENFILENAME)) GetProcAddress (hComDlg32, "GetOpenFileNameA");
  1685.     } else
  1686.     /* System administrator? ROFL! -- Bernd */
  1687.     MyOutputDebugString ("COMDLG32.DLL not available. Please contact your system administrator.\n");
  1688.  
  1689.     /* LoadLibrary the richedit control stuff */
  1690.     if ((hRichEdit = LoadLibrary ("RICHED32.DLL")) == NULL) {
  1691.     MyOutputDebugString ("RICHED32.DLL not available. Please contact your system administrator.\n");
  1692.     }
  1693.     if (hDDraw = LoadLibrary ("DDRAW.DLL")) {
  1694. #ifdef __GNUC__
  1695.     pDirectDrawCreate = (HRESULT (WINAPI *) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *)) GetProcAddress (hDDraw, "DirectDrawCreate");
  1696. #endif
  1697.     InitializeCriticalSection (&csDraw);
  1698.  
  1699.     process_desired_pri = IDLE_PRIORITY_CLASS;
  1700.  
  1701.     return 1;
  1702.     } else
  1703.     MyOutputDebugString ("You have to install DirectX on your system before you can use UAE.\nRefer to the documentation for further details.\n");
  1704.  
  1705.     return 0;
  1706. }
  1707.  
  1708. void MyOutputDebugString (char *format,...)
  1709. {
  1710.     char buffer[512];
  1711.     va_list parms;
  1712.  
  1713.     va_start (parms, format);
  1714.     vsprintf (buffer, format, parms);
  1715.     va_end (parms);
  1716.     write_log (buffer);
  1717. }
  1718.  
  1719. void write_log (const char *txt)
  1720. {
  1721.     DWORD numwritten;
  1722. #ifdef _DEBUG
  1723.     OutputDebugString( txt );
  1724. #endif
  1725.     fprintf (stderr, "%s", txt);
  1726.     /* if (HasConsole)
  1727.     WriteConsole (stdouthandle, txt, strlen (txt), &numwritten, NULL);*/
  1728.     WriteFile (debugfile, txt, strlen (txt), &numwritten, NULL);
  1729. }
  1730.  
  1731. int debuggable (void)
  1732. {
  1733.     return 1;
  1734. }
  1735.  
  1736. int needmousehack (void)
  1737. {
  1738.     return 1;
  1739. }
  1740.  
  1741. void LED (int on)
  1742. {
  1743. }
  1744.  
  1745.  
  1746. static uae_u16 *ppicasso_format;
  1747. static int picasso_modecount;
  1748.  
  1749. static HRESULT CALLBACK modesCallback (LPDDSURFACEDESC modeDesc, LPVOID context)
  1750. {
  1751.     int bpp;
  1752.  
  1753.     if (picasso_modecount >= MAX_PICASSO_MODES)
  1754.     return DDENUMRET_CANCEL;
  1755.  
  1756.     if (modeDesc->dwFlags & (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE)) {
  1757.     bpp = modeDesc->ddpfPixelFormat.dwRGBBitCount;
  1758. #ifdef PICASSO96
  1759.     switch (bpp) {
  1760.     case 8:
  1761.         *ppicasso_format |= RGBFF_CHUNKY;
  1762.         break;
  1763.     case 16:
  1764.         /* figure out which actual format it is using based on the RGB masks */
  1765.  
  1766.         /* Bernd - this doesn't work for some reason.  Instead, I figure out the modes in doInit(),
  1767.          *         where I have the surface's description and pixel formats.  Damned DirectDraw stuff!
  1768.          */
  1769.         break;
  1770.     case 24:
  1771.         /* figure out which actual format it is using based on the RGB masks */
  1772.         if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x00FF0000)
  1773.         *ppicasso_format |= RGBFF_B8G8R8;
  1774.         else
  1775.         *ppicasso_format |= RGBFF_R8G8B8;
  1776.         break;
  1777.     case 32:
  1778.         /* figure out which actual format it is using based on the RGB masks */
  1779.         if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x00FF0000)
  1780.         *ppicasso_format |= RGBFF_B8G8R8A8;
  1781.         else if (modeDesc->ddpfPixelFormat.dwRBitMask == 0x000000FF)
  1782.         *ppicasso_format |= RGBFF_R8G8B8A8;
  1783.         else if (modeDesc->ddpfPixelFormat.dwBBitMask == 0xFF000000)
  1784.         *ppicasso_format |= RGBFF_A8R8G8B8;
  1785.         else
  1786.         *ppicasso_format |= RGBFF_A8B8G8R8;
  1787.         break;
  1788.     }
  1789. #endif
  1790.     DisplayModes[picasso_modecount].res.width = modeDesc->dwWidth;
  1791.     DisplayModes[picasso_modecount].res.height = modeDesc->dwHeight;
  1792.     DisplayModes[picasso_modecount].depth = bpp/8;
  1793.     if (modeDesc->dwRefreshRate)
  1794.     {
  1795.         sprintf(DisplayModes[picasso_modecount].name,"%dx%d, %d-bit, %d Hz",modeDesc->dwWidth,
  1796.             modeDesc->dwHeight, bpp, modeDesc->dwRefreshRate );
  1797.         DisplayModes[picasso_modecount].refresh = modeDesc->dwRefreshRate;
  1798.     }
  1799.     else
  1800.     {
  1801.         sprintf(DisplayModes[picasso_modecount].name,"%dx%d, %d-bit",modeDesc->dwWidth,
  1802.             modeDesc->dwHeight, bpp );
  1803.         DisplayModes[picasso_modecount].refresh = 75; /* fake a 75-Hz refresh rate... BLAH! */
  1804.     }
  1805.     picasso_modecount++;
  1806.     }
  1807.     return DDENUMRET_OK;
  1808. }
  1809.  
  1810. int DX_FillResolutions (uae_u16 *ppixel_format)
  1811. {
  1812.     static int from_preInit = 1;
  1813.     if( from_preInit )
  1814.     {
  1815.         picasso_modecount = 0;
  1816.         *ppixel_format = 0;
  1817.         ppicasso_format = ppixel_format;
  1818.  
  1819.         IDirectDraw_EnumDisplayModes (lpDD, 0, NULL, NULL, modesCallback);
  1820.         from_preInit = 0;
  1821.     }
  1822.     return picasso_modecount;
  1823. }
  1824.  
  1825. #ifdef PICASSO96
  1826.  
  1827. void DX_SetPalette (int start, int count)
  1828. {
  1829.     HRESULT ddrval;
  1830.  
  1831.     if (!screen_is_picasso)
  1832.     return;
  1833.  
  1834.     /* Set our DirectX palette here */
  1835.     if (lpDDP && (picasso96_state.BytesPerPixel == 1)) {
  1836.     /* For now, until I figure this out, just set the entire range of CLUT values */
  1837.     ddrval = IDirectDrawPalette_SetEntries (lpDDP, 0, 0, 256, (LPPALETTEENTRY) &picasso96_state.CLUT);
  1838.     if (ddrval != DD_OK)
  1839.         MyOutputDebugString ("DX_SetPalette() failed with %s/%d\n", getddrname (ddrval), ddrval);
  1840.     } else
  1841.     MyOutputDebugString ("ERROR - DX_SetPalette() doesn't have palette, or isn't Chunky mode.\n");
  1842. }
  1843.  
  1844. void DX_Invalidate (int first, int last)
  1845. {
  1846. }
  1847.  
  1848. int DX_BitsPerCannon (void)
  1849. {
  1850.     return 8;
  1851. }
  1852.  
  1853. int DX_FillRect (uaecptr addr, uae_u16 X, uae_u16 Y, uae_u16 Width, uae_u16 Height, uae_u32 Pen, uae_u8 Bpp)
  1854. {
  1855.     return 0;
  1856. }
  1857.  
  1858. void gfx_set_picasso_state (int on)
  1859. {
  1860.     if (screen_is_picasso == on)
  1861.     return;
  1862.     screen_is_picasso = on;
  1863.     PostMessage (hAmigaWnd, WM_USER + 0x201, 0, 0);
  1864.     uae_sem_wait (&picasso_switch_sem);
  1865. }
  1866.  
  1867. void gfx_set_picasso_modeinfo (int w, int h, int depth)
  1868. {
  1869.     depth >>= 3;
  1870.     if (picasso_vidinfo.width == w
  1871.     && picasso_vidinfo.height == h
  1872.     && picasso_vidinfo.depth == depth)
  1873.     return;
  1874.  
  1875.     picasso_vidinfo.width = w;
  1876.     picasso_vidinfo.height = h;
  1877.     picasso_vidinfo.depth = depth;
  1878.     picasso_vidinfo.extra_mem = 1;
  1879.  
  1880.     if (screen_is_picasso) {
  1881.     PostMessage (hAmigaWnd, WM_USER + 0x201, 0, 0);
  1882.     uae_sem_wait (&picasso_switch_sem);
  1883.     }
  1884. }
  1885.  
  1886. #endif
  1887.